package com.qfedu.wmsuser.user.service.impl;

import com.qfedu.common.core.common.R;
import com.qfedu.common.core.constant.CommonConstant;
import com.qfedu.common.core.entity.UserStaff;
import com.qfedu.common.core.utils.TokenUtils;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.qfedu.common.core.entity.User;
import com.qfedu.common.core.exception.CommonException;
import com.qfedu.common.core.utils.JwtUtils;
import com.qfedu.common.redis.utils.RedisUtil;
import com.qfedu.oss.utils.AliyunOSSUtil;
import com.qfedu.oss.utils.FileUploadResult;
import com.qfedu.wmsuser.user.mapper.UserMapper;
import com.qfedu.wmsuser.user.mapper.UserStaffMapper;
import com.qfedu.wmsuser.user.param.LoginParam;
import com.qfedu.wmsuser.user.param.LoginParam1;
import com.qfedu.wmsuser.user.service.UserService;
import com.qfedu.wmsuser.user.vo.UserStaffVO;
import com.qfedu.wmsuser.user.vo.UserVO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import reactor.core.publisher.Mono;

import javax.annotation.Resource;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ThreadPoolExecutor;


/**
 * @author zsjx
 *
 * 业务层调用本模块的dao层，调用其他模块的业务层
 */
@Service
public class UserServiceImpl implements UserService {

    private static final Logger log = LoggerFactory.getLogger(UserServiceImpl.class);
    @Resource
    private UserMapper userMapper;

    @Resource
    private UserStaffMapper userStaffMapper;

    @Resource
    private RedisUtil redisUtil;


    // 创建线程池
    @Resource
    private ThreadPoolExecutor threadPoolExecutor;

    @Override
    public String login(LoginParam loginParam) {

        // 验证用户名密码是否正确
        User user = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUsername, loginParam.getUsername()));

        if (user == null) {
            throw new CommonException("用户名不存在");
        }

        // 加密验证
        // 针对前端传来的密码进行md5加密
        String md5pwd = SecureUtil.md5(loginParam.getPassword());

        // 验证密码
        if (!user.getPassword().equals(md5pwd)) {
            throw new CommonException("密码错误");
        }

        // 验证成功，返回token
/*
        // 方案1：token + redis
        String token = UUID.randomUUID().toString().replace("-", "");
        String key = "token:" + token;
        // 拼接key "token:%s"
//        String key = String.format(RedisKeyEnum.KEY_LOGIN.getKey(), token);
        // 将token存入redis
//        redisUtil.setCacheObject(key, user, RedisKeyEnum.KEY_LOGIN.getTime(), TimeUnit.SECONDS);
        redisUtil.setCacheObject(key, user, 60 * 60 * 24, TimeUnit.SECONDS);
*/

        // 方案2：JWT做token
        Map<String, Object> map = new HashMap<>();
        map.put("userId", user.getId());
        String token = JwtUtils.createJwt(map);

        return token;

    }

    @Override
    public Mono<UserVO> my1(ServerHttpRequest request) {
        String token = request.getHeaders().getFirst(CommonConstant.TOKEN);
        if (token == null) {
            return Mono.error(new RuntimeException("No Token available"));
        }

        return Mono.justOrEmpty(TokenUtils.getUserIdFromRequest(token))
                .flatMap(userId -> {
                    log.info("userId: {}", userId);
                    return Mono.justOrEmpty(userMapper.selectUserVOById(userId.block()));
                });
    }

    @Override
    public Mono<R> logout(ServerHttpRequest request) {
        String token = request.getHeaders().getFirst(CommonConstant.TOKEN);
        if (token == null) {
            return Mono.just(R.fail("No token found for logout"));
        }

        // 清除token逻辑，这里假设你使用的是JWT，那么直接让token过期或从redis中移除token
        // JWT token通常没有服务器端状态，所以这里的处理可能只是简单地通知客户端token已失效
        // 如果使用Redis来存储token，那么可以从Redis中删除token
        return Mono.fromCallable(() -> {
            // 这里只是一个示例逻辑，如果你使用的是Redis来存储token
            // redisUtil.del("token:" + token);
            log.info("Token {} has been invalidated", token);
            return "Logout successful";
        }).map(msg -> R.ok(msg, null));
    }

    @Override
    public UserVO my() {

        Integer userId = TokenUtils.getUserId();
        log.info("userId: {}", userId);
        return userMapper.selectUserVOById(userId);
    }

    @Override
    public String login1(LoginParam1 loginParam1) {
        // 验证用户名密码是否正确
        User user = userMapper.selectOne(
                new LambdaQueryWrapper<User>()
                        .eq(User::getUsername, loginParam1.getUsername()));

        UserStaff userStaff = userStaffMapper.selectOne(
                new LambdaQueryWrapper<UserStaff>()
                        .eq(UserStaff::getUserStaffName, loginParam1.getUsername()));

        if (userStaff == null) {
            throw new CommonException("用户名不存在");
        }

        // 加密验证
        // 针对前端传来的密码进行md5加密
        String md5pwd = SecureUtil.md5(loginParam1.getPassword());

        // 验证密码
        if (!userStaff.getPassword().equals(md5pwd)) {
            throw new CommonException("密码错误");
        }

        // 方案2：JWT做token
        Map<String, Object> map = new HashMap<>();
        map.put("userId", userStaff.getUserStaffId());
        String token = JwtUtils.createJwt(map);

        return token;
    }

    @Override
    public Mono<UserStaffVO> my2(ServerHttpRequest request) {
        String token = request.getHeaders().getFirst(CommonConstant.TOKEN);
        if (token == null) {
            return Mono.error(new RuntimeException("No Token available"));
        }

        return Mono.justOrEmpty(TokenUtils.getUserIdFromRequest(token))
                .flatMap(userId -> {
                    log.info("userId: {}", userId);
                    return Mono.justOrEmpty(userStaffMapper.selectUserStaffVOById(userId.block()));
                });
    }

    @Override
    public int insertUserStaff(UserStaff userStaff) {
        // md5加密密码
        userStaff.setPassword(SecureUtil.md5(userStaff.getPassword()));
        // 如果头像为空字符串，则设置为默认头像
        if ("".equals(userStaff.getAvatar())) {
            userStaff.setAvatar(null);
        }
        return userStaffMapper.insert(userStaff);
    }

    @Override
    public int updateUserStaff(UserStaff userStaff) {
        // md5加密密码
        userStaff.setPassword(SecureUtil.md5(userStaff.getPassword()));
        // 如果头像为空字符串，则设置为默认头像
        if ("".equals(userStaff.getAvatar())) {
            userStaff.setAvatar("https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif");
        }
        return userStaffMapper.updateById(userStaff);
    }

    @Override
    public int deleteById(Integer id) {
        return userStaffMapper.deleteById(id);
    }

    @Override
    public R uploadAvatar(MultipartFile file) {
        if (file != null) {
            Integer userStaffId = TokenUtils.getUserId();
            FileUploadResult fileUploadResult = AliyunOSSUtil.upLoad(file);
            // 将头像地址保存到数据库
            UserStaff userStaff = new UserStaff();
            userStaff.setUserStaffId(userStaffId);
            userStaff.setAvatar(fileUploadResult.getFileUrl());
            userStaffMapper.updateById(userStaff);
            String fileUrl = fileUploadResult.getFileUrl();
            return R.ok("上传成功", fileUrl);
        }
        return R.fail("上传失败");
    }
}
